home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / rng.exe / RANDOM.FOR < prev    next >
Text File  |  1989-03-12  |  5KB  |  162 lines

  1. C This random number generator originally appeared in "Toward a Universal 
  2. C Random Number Generator" by George Marsaglia and Arif Zaman. 
  3. C Florida State University Report: FSU-SCRI-87-50 (1987)
  4. C It was later modified by F. James and published in "A Review of Pseudo-
  5. C random Number Generators" 
  6. C THIS IS THE BEST KNOWN RANDOM NUMBER GENERATOR AVAILABLE.
  7. C       (However, a newly discovered technique can yield 
  8. C         a period of 10^600. But that is still in the development stage.)
  9. C
  10. C It passes ALL of the tests for random number generators and has a period 
  11. C   of 2^144, is completely portable (gives bit identical results on all 
  12. C   machines with at least 24-bit mantissas in the floating point 
  13. C   representation). 
  14. C The algorithm is a combination of a Fibonacci sequence (with lags of 97
  15. C   and 33, and operation "subtraction plus one, modulo one") and an 
  16. C   "arithmetic sequence" (using subtraction).
  17. C
  18. C On a Vax 11/780, this random number generator can produce a number in 
  19. C    13 microseconds. 
  20. C======================================================================== 
  21.  
  22.       PROGRAM TstRAN
  23.       REAL temp(100)
  24.       INTEGER IJ, KL, len
  25. C These are the seeds needed to produce the test case results
  26.       IJ = 1802
  27.       KL = 9373
  28.  
  29.  
  30. C Do the initialization
  31.       call rmarin(ij,kl)
  32.  
  33. C Generate 20000 random numbers
  34.       len = 100
  35.       do 10 i = 1, 200
  36.          call RANMAR(temp, len)
  37. 10    continue
  38.  
  39. C If the random number generator is working properly, the next six random
  40. C numbers should be:
  41. C           6533892.0  14220222.0  7275067.0
  42. C           6172232.0  8354498.0   10633180.0
  43.  
  44.       len = 6
  45.       call RANMAR(temp, len)
  46.  
  47.         
  48.       write(6,20) (4096.0*4096.0*temp(I), I=1,6)
  49. 20    format (3f12.1)
  50.       end
  51.  
  52.       subroutine RMARIN(IJ,KL)
  53. C This is the initialization routine for the random number generator RANMAR()
  54. C NOTE: The seed variables can have values between:    0 <= IJ <= 31328
  55. C                                                      0 <= KL <= 30081
  56. C The random number sequences created by these two seeds are of sufficient 
  57. C length to complete an entire calculation with. For example, if sveral 
  58. C different groups are working on different parts of the same calculation,
  59. C each group could be assigned its own IJ seed. This would leave each group
  60. C with 30000 choices for the second seed. That is to say, this random 
  61. C number generator can create 900 million different subsequences -- with 
  62. C each subsequence having a length of approximately 10^30.
  63. C Use IJ = 1802 & KL = 9373 to test the random number generator. The
  64. C subroutine RANMAR should be used to generate 20000 random numbers.
  65. C Then display the next six random numbers generated multiplied by 4096*4096
  66. C If the random number generator is working properly, the random numbers
  67. C should be:
  68. C           6533892.0  14220222.0  7275067.0
  69. C           6172232.0  8354498.0   10633180.0
  70.  
  71.  
  72.       real U(97), C, CD, CM
  73.       integer I97, J97
  74.       logical TEST
  75.       data TEST /.FALSE./
  76.       common /raset1/ U, C, CD, CM, I97, J97, TEST
  77.  
  78.       if( IJ .lt. 0  .or.  IJ .gt. 31328  .or.
  79.      *    KL .lt. 0  .or.  KL .gt. 30081 ) then
  80.           print '(A)', ' The first random number seed must have a value 
  81.      *between 0 and 31328'
  82.           print '(A)',' The second seed must have a value between 0 and         
  83.      *30081'
  84.             stop
  85.       endif
  86.  
  87.       i = mod(IJ/177, 177) + 2
  88.       j = mod(IJ    , 177) + 2
  89.       k = mod(KL/169, 178) + 1
  90.       l = mod(KL,     169) 
  91.  
  92.       do 2 ii = 1, 97
  93.          s = 0.0
  94.          t = 0.5
  95.          do 3 jj = 1, 24
  96.             m = mod(mod(i*j, 179)*k, 179)
  97.             i = j
  98.             j = k
  99.             k = m
  100.             l = mod(53*l+1, 169)
  101.             if (mod(l*m, 64) .ge. 32) then
  102.                s = s + t
  103.             endif
  104.             t = 0.5 * t
  105. 3        continue
  106.          U(ii) = s
  107. 2     continue
  108.  
  109.       C = 362436.0 / 16777216.0
  110.       CD = 7654321.0 / 16777216.0
  111.       CM = 16777213.0 /16777216.0
  112.  
  113.       I97 = 97
  114.       J97 = 33
  115.  
  116.       TEST = .TRUE.
  117.       return
  118.       end
  119.  
  120.       subroutine ranmar(RVEC, LEN)
  121. C This is the random number generator proposed by George Marsaglia in 
  122. C Florida State University Report: FSU-SCRI-87-50
  123. C It was slightly modified by F. James to produce an array of pseudorandom
  124. C numbers.
  125.       REAL RVEC(*)
  126.       real U(97), C, CD, CM
  127.       integer I97, J97
  128.       logical TEST
  129.       common /raset1/ U, C, CD, CM, I97, J97, TEST
  130.  
  131.       integer ivec
  132.  
  133.       if( .NOT. TEST ) then
  134.          print '(A)',' Call the init routine (RMARIN) before calling RAN        
  135.      *MAR'  
  136.          stop
  137.       endif
  138.  
  139.       do 100 ivec = 1, LEN
  140.          uni = U(I97) - U(J97)
  141.          if( uni .lt. 0.0 ) uni = uni + 1.0
  142.          U(I97) = uni
  143.          I97 = I97 - 1
  144.          if(I97 .eq. 0) I97 = 97
  145.          J97 = J97 - 1
  146.          if(J97 .eq. 0) J97 = 97
  147.          C = C - CD
  148.          if( C .lt. 0.0 ) C = C + CM
  149.          uni = uni - C
  150.          if( uni .lt. 0.0 ) uni = uni + 1.0
  151.          RVEC(ivec) = uni
  152. 100   continue
  153.       return
  154.       end
  155.  
  156. ------------------------------
  157.  
  158.